home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / math / gle-3.000 / gle-3 / gle / bmp.c < prev    next >
C/C++ Source or Header  |  1995-02-07  |  35KB  |  1,211 lines

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <ctype.h>
  4. #include <string.h>
  5. #include <assert.h>
  6. #include <math.h>
  7. #include "int32.h"
  8. #ifdef __TURBOC__
  9. #include <mem.h>
  10. #include <alloc.h>
  11. #else
  12. #define farcalloc calloc
  13. #define farcoreleft() (1200000)
  14. #endif
  15. #ifdef unix
  16. #ifndef EXIT_FAILURE
  17. #define EXIT_FAILURE 1
  18. #endif
  19. #endif
  20. #if (defined DJ || defined EMXOS2 )              /* a.r. */
  21. #define EXIT_FAILURE 1
  22. #endif
  23.  
  24. #include "bmp.h"
  25. #define CLIPSIZE ((int32) PWIDTH* (int32) sizeof(int)* (int32) (b->ny+2))
  26. #define dbg if (gdebug==true)
  27.  
  28. #define false  0
  29. #define true !0
  30. extern int gdebug;
  31. int iscolor;
  32. extern int dev_noclip;
  33.  
  34. int row_show(char *s,Run *r,int y);
  35. int row_init(Run *r, int ny);
  36. int bmp_paintsort(int *p, int np);
  37. int row_free(Run *r, int ny);
  38. int row_grow(Run *r, int y, int v);
  39. int bmp_ink4(Bitmap *bb,unsigned int savem,int cindex);
  40. int bmp_ink16(Bitmap *bb,unsigned int newink[],int cindex);
  41. int bmpcheck(Bitmap *b);
  42.  
  43. /*
  44.         Filling routines to allow an arbitrary dimensioned
  45.         bitmap to be drawn into.
  46. */
  47.  
  48. /* General notes:
  49.         Color and pattern are the same thing, on a
  50.         color system the pattern array would have the
  51.         same depth as the bitmap itself.
  52.  
  53.         White bit = 1;
  54.         Black bit = 0;
  55. */
  56.  
  57.  
  58. /*  allocates the storage required.
  59.         initializes it
  60.         returns NULL if not enough memory
  61.         returns pointer to Bitmap structure
  62.         (ignoring depth at the moment)
  63.  
  64. */
  65.  
  66. /* FILE *fgle; */
  67. Bitmap *bmp_open(int xsize,int ysize,int depth, int bmp_compress)
  68. {
  69.         Bitmap *b;
  70.         int *p;
  71.         int i,j;
  72.  
  73. /*  fgle = fopen("test.gle","w");
  74.         fprintf(fgle,"size 15 15\n");
  75.         fprintf(fgle,"scale .3 .3 \n");
  76. */
  77.         b = (Bitmap *) calloc(1,sizeof(Bitmap));
  78.         if (b==NULL) bmp_die("No memory for Bitmap structure\n");
  79.         b->nx = xsize;
  80.         b->ny = ysize;
  81.                 b->compress = bmp_compress;
  82.  
  83.         row_init(&b->clip,b->ny);
  84.         row_init(&b->paint,b->ny);
  85.         row_init(&b->horiz,b->ny);
  86.  
  87.         b->data = (char *(*)[]) calloc(1,sizeof(int *) * (ysize+3));
  88.         if (b->data == NULL) bmp_die("No memory for bitmap pointers \n");
  89.  
  90.         { int32 x;
  91.                 if (iscolor) x=xsize/2;
  92.                 else x=xsize/8;
  93.                 x = x*ysize+80000L;
  94.                 if (farcoreleft() < x) b->compress = true;
  95.         }
  96.         if (b->compress) printf("Compressing internal bitmap to save memory\n");
  97.  
  98.         if (b->compress==false) {
  99.           for (i=0; i<=ysize+1; i++) {
  100.                 if (iscolor) {
  101.                 if ( ((*b->data)[i] = calloc(1,xsize/2+2)) == NULL)
  102.                         bmp_die("No memory for bitmap\n");
  103.                 memset( (*b->data)[i], 255, xsize/2+2);
  104.                 } else {
  105.                 if ( ((*b->data)[i] = calloc(1,xsize/8+2)) == NULL)
  106.                         bmp_die("No memory for bitmap\n");
  107.                 memset( (*b->data)[i], 255, xsize/8+2);
  108.                 }
  109.           }
  110.         }
  111.         b->painty1 = ysize;
  112.         b->lwidth = 1;
  113.         b->lstyle = 0x8000001e;
  114.         b->lstyle_mask = 0x80000000;
  115.                 b->lstyle_dotlen = 1;
  116.                 b->lstyle_dotpix = 0;
  117.         bmp_color(b,0);
  118. #ifdef __TURBOC__
  119. /*  printf("Free memory after bitmap allocated %ld \n",farcoreleft()); */
  120. #endif
  121.         return b;
  122. }
  123. row_init(Run *r, int ny)
  124. {
  125.         r->alloc = (unsigned char *) calloc(1,ny+3);
  126.         if (r->alloc == NULL) bmp_die("Not enough  memory for run counts \n");
  127.         r->used = (unsigned char *) calloc(1,ny+3);
  128.         if (r->used == NULL) bmp_die("Not enough  memory for run counts \n");
  129.         r->row = (typrow) calloc(sizeof(int *),ny+3);
  130.         if (r->row == NULL) bmp_die("Not enough  memory for run counts \n");
  131. }
  132. row_free(Run *r, int ny)
  133. {
  134.         int i,*rr;
  135.         for (i=0;i<=ny;i++) {
  136.                 rr = (*r->row)[i];
  137.                 if (rr!=NULL)  free(rr);
  138.         }
  139.         free(r->row);
  140.         free(r->used);
  141.         free(r->alloc);
  142. }
  143. int row_shrinkx(Run *r, int ny);
  144. int row_shrink(Bitmap *b);
  145. row_shrink(Bitmap *b)
  146. {
  147.         row_shrinkx(&b->paint,b->ny);
  148.         row_shrinkx(&b->horiz,b->ny);
  149. }
  150. row_shrinkx(Run *r, int ny)
  151. {
  152.         int i,*rr;
  153.         for (i=0;i<=ny;i++) {
  154.                 rr = (*r->row)[i];
  155.                 if (rr!=NULL)  free(rr);
  156.                 (*r->row)[i] = NULL;
  157.                 r->used[i] = 0;
  158.                 r->alloc[i] = 0;
  159.         }
  160. }
  161. #define row_data(r,y)   ( (*r.row)[y] )
  162. #define row_used(r,y)   ( r.used[y] )
  163. #define row_setused(r,y,v) ( r.used[y] = v )
  164. row_grow(Run *r, int y, int v)
  165. {
  166.         int vv;
  167.         int *z;
  168.         v += r->used[y];
  169.         if (v<= r->alloc[y]) {
  170.                 r->used[y] = v;
  171.                 return;
  172.         }
  173.         vv = v;
  174.         if ((v&1)==1) vv++;
  175.         z = (*r->row)[y] ;
  176.         if (z==NULL) z = (int *) malloc(vv*sizeof(int));
  177.         else z = (int *) realloc((*r->row)[y],vv*sizeof(int));
  178. /*
  179.         if (z==NULL) z = malloc(vv*sizeof(int));
  180.         else {
  181.                 z = malloc(vv*sizeof(int));
  182.                 memcpy(z, (*r->row)[y] ,r->used[y]*sizeof(int));
  183.                 free( (*r->row)[y] );
  184.         }
  185. */
  186.         (*r->row)[y] = z;
  187.                 /* malloc(v);   */
  188.         if ((*r->row)[y] == NULL) bmp_die("Could not grow row count data \n");
  189.         r->alloc[y] = vv;
  190.         r->used[y] = v;
  191. }
  192.  
  193. /*  frees up all storage. */
  194. iffree(void *block)
  195. {
  196.         if (block!=NULL) free(block);
  197. }
  198. bmp_close(Bitmap *b)
  199. {
  200.         int i,j;
  201.         if (b==NULL) return;
  202.         for (i=0; i<=b->ny+2; i++) {
  203.                 iffree((*b->data)[i]);
  204.         }
  205.         row_free(&b->paint,b->ny);
  206.         row_free(&b->clip,b->ny);
  207.         row_free(&b->horiz,b->ny);
  208. /*  fclose(fgle);  */
  209. }
  210.  
  211. /*
  212.         Draws line of current lwidth, lstyle,
  213.         and color/pattern
  214.  
  215.         Line is clipped using clip array.
  216. */
  217. #define sign(x) ((x) > 0 ? 1:  ((x) == 0 ? 0:  (-1)))
  218. bmp_line(Bitmap *b,int x1,int y1,int x2,int y2)
  219. {
  220.         int dx, dy, dxabs, dyabs, i, j, px, py, sdx, sdy;
  221.         register int x,y;
  222.         uint32 mask,pattern,lastpatbit;
  223.         int lwidth, dotlen,pix;
  224.  
  225.         lwidth = b->lwidth/2;
  226.         mask = b->lstyle_mask;
  227.         pattern = b->lstyle;
  228.         lastpatbit = 1l << (pattern & 0x1f);
  229.         dotlen = b->lstyle_dotlen;
  230.         pix = b->lstyle_dotpix;
  231.  
  232. /*  printf("lstyle %08lx, mask %08lx, dotlen %d, dotpix %d, lastpatbit %8lx pat= %lx \n",
  233.         pattern,mask,dotlen,pix,lastpatbit,pattern & 0x1f);
  234. */
  235.         if (bmp_clipline(b,&x1,&y1,&x2,&y2)) return;    /* clip to bitmap */
  236.         dx = x2 - x1;
  237.         dy = y2 - y1;
  238.         sdx = sign(dx);
  239.         sdy = sign(dy);
  240.         dxabs = abs(dx);
  241.         dyabs = abs(dy);
  242.         x = 0;
  243.         y = 0;
  244.         px = x1;
  245.         py = y1;
  246.  
  247.         if (dxabs >= dyabs) {
  248.            mask = (mask & lastpatbit) ? 0x80000000 : mask;
  249.            if (pattern & mask) {
  250.                   for (j= -lwidth; j<=lwidth; j++)
  251.                 bmp_pixel(b,px,py+j);
  252.            }
  253.            if ((++pix) >= dotlen)  {mask >>= 1; pix=0;}
  254.            for (i=0; i<dxabs; i++) {
  255.                   mask = (mask & lastpatbit) ? 0x80000000 : mask;
  256.                   y += dyabs;
  257.                   if (y>=dxabs) {
  258.                  y -= dxabs;
  259.                  py += sdy;
  260.                   }
  261.                   px += sdx;
  262.                   if (pattern & mask) {
  263.                  for (j= -lwidth; j<=lwidth; j++)
  264.                         bmp_pixel(b,px,py+j);
  265.                   }
  266.                   if ((++pix) >= dotlen)  {mask >>= 1; pix=0;}
  267.            }
  268.         } else {
  269.            mask = (mask & lastpatbit) ? 0x80000000 : mask;
  270.            if (pattern & mask) {
  271.                   for (j= -lwidth; j<=lwidth; j++)
  272.                  bmp_pixel(b,px+j,py);
  273.            }
  274.            if ((++pix) >= dotlen)  {mask >>= 1; pix=0;}
  275.            for (i=0; i<dyabs; i++) {
  276.                   mask = (mask & lastpatbit) ? 0x80000000 : mask;
  277.                   x += dxabs;
  278.                   if (x>=dyabs) {
  279.                  x -= dyabs;
  280.                  px += sdx;
  281.                   }
  282.                   py += sdy;
  283.                   if (pattern & mask) {
  284.                  for (j= -lwidth; j<=lwidth; j++)
  285.                         bmp_pixel(b,px+j,py);
  286.                   }
  287.                   if ((++pix) >= dotlen)  {mask >>= 1; pix=0;}
  288.            }
  289.         }
  290.  
  291.         b->lstyle_mask = mask;
  292.         b->lstyle_dotpix = pix;
  293. /*  printf("lstyle %08x, mask %08x, lastpatbix %08x, dotpix %d \n",
  294.                    pattern, mask, lastpatbit, pix); */
  295.  
  296. }
  297.  
  298. /*
  299.         Apply clipping
  300.         Get bit from ink
  301.         Get row of bitmap
  302.         Place bit into row
  303. */
  304. static Bitmap *pr_lb;
  305. static int pr_ly;
  306. static char *pr_row;
  307. bmp_pixel(register Bitmap *b,register int x,register int y)
  308. {
  309.         static int i,spot;
  310.         int ry;
  311. /*  static char *row; */
  312.         unsigned char *k;
  313.  
  314.         if (b->clipping) if (bmp_invis(b,x,y)) return;
  315.         if (x> b->nx || x<0 || y>b->ny || y<0) return;
  316.         ry = y % 16;
  317.         if (pr_ly!=y || pr_lb!=b) {
  318.                 pr_row = bmp_row(b,y);
  319.                 pr_ly = y; pr_lb = b;
  320.         }
  321.  
  322.         k = (unsigned char *) &b->ink[ry%16][0];
  323.         spot = k[x%16];
  324.         if (iscolor) {
  325.                 i = pr_row[x/2];
  326.                 if (x % 2==0) {
  327.                         i = (i & 0x0f) | (spot << 4);
  328.                 } else {
  329.                         i = (i & 0xf0) | spot;
  330.                 }
  331.                 pr_row[x/2] = i;
  332.                 return;
  333.         }
  334.  
  335.  
  336.         if (k[x % 16] != 0) { /* a white spot */
  337.           *(pr_row + x/8) |= (1 << (x%8));
  338.         } else {
  339.           *(pr_row + x/8) &= (255-(1 << (x%8)));
  340.         }
  341. }
  342. bmp_paintrange(Bitmap *b,int y, register int x1, int x2)
  343. {
  344.         static int i,spot;
  345.         int ry;
  346. /*  static char *p;*/
  347.         unsigned char *k;
  348.  
  349. /* debugging stuff */
  350.         if (x1==-2 || x2==-2) {
  351.                 printf("********Stuffed range on line %d, %d-->%d \n",y,x1,x2);
  352.                 return;
  353.         }
  354.         dbg printf("Paint range %d, %d %d \n",y,x1,x2);
  355.  
  356. /* end debug */
  357. /*  printf("Paint range %d, %d %d \n",y,x1,x2);*/
  358.         ry = y % 16;
  359.         if (pr_ly!=y || pr_lb!=b) {
  360.                 pr_row = bmp_row(b,y);
  361.                 pr_ly = y; pr_lb = b;
  362.         }
  363.  
  364.  
  365.         k = (unsigned char  *) &b->ink[ry%16][0];
  366.  
  367.         if (iscolor) {
  368.           for (;x1<=x2;x1++) {
  369.                 spot = k[x1%16];
  370.                 i = pr_row[x1/2];
  371.                 if (x1 % 2==0) {
  372.                         i = (i & 0x0f) | (spot << 4);
  373.                 } else {
  374.                         i = (i & 0xf0) | spot;
  375.                 }
  376.                 pr_row[x1/2] = i;
  377.           }
  378.           return;
  379.         }
  380.  
  381.         for (;x1<=x2;x1++) {
  382.           if (k[x1 % 16] != 0) { /* a white spot */
  383.                 *(pr_row + x1/8) |= (1 << (x1%8));
  384.           } else {
  385.                 *(pr_row + x1/8) &= (255-(1 << (x1%8)));
  386.           }
  387.         }
  388. }
  389.  
  390. /* return true if pixel at that
  391.    location is clipped
  392. */
  393. int bmp_invis(Bitmap *b, int x, int y)
  394. {
  395.         int *c,nc,i;
  396.  
  397.         if (! b->clipping) return false; /* clipping os off */
  398.         c = row_data(b->clip,y);
  399.         if (*c==0) return true; /* clipping */
  400.         nc = row_used(b->clip,y);
  401.         for (i=0;i<nc-1;i+=2, c+=2) {
  402.                  if ( (x>= *c) && (x<= *(c+1))) return false; /* is visible */
  403.         }
  404.         return true;
  405. }
  406.  
  407. /*
  408.         Adds x values at y crossings onto the paint[] array.
  409.         Doesn't add last crossing
  410.         Sets maxy,miny
  411.  
  412.         Special cases:
  413.  
  414. move
  415.         init lddy
  416.                 sx,sy, x1,y1 ...
  417.  
  418.         * Change in sdy
  419.                 put in double x value
  420.         * When end of line meets start of line.
  421.                 remember start of line with bmp_pmove
  422.                 remember start sdy
  423.                 if sdy == enddy then don't put endx,endy
  424.                 start new polygon.
  425.                 (at fill check lines is closed, if not then close before fill)
  426.         * (WRONG) Start of Horizontal lines
  427.                 put in start xvalue, (if not first line in path)
  428.         * Continued horizontal line
  429.                 do nothing
  430.         * (WRONG) end of horizontal line
  431.                 Put in last x(thisy) value
  432.  
  433.         * with horizontal lines or lines which have multiple x values
  434.         store the range of values into b->horiz[][] so they can
  435.         also be drawn in.  This gets the middle of an H or A or top
  436.         of a B drawn correctly if the bar is very thin.
  437. */
  438. bmp_pmove(Bitmap *b,int x1,int y1)
  439. {
  440.         bmp_clipline(b,&x1,&y1,&x1,&y1);    /* clip to bitmap */
  441.         /* fprintf(fgle,"amove %d %d \n",x1,y1); */
  442.         if (b->sx != b->x1 || b->sy != b->y1) {
  443.                 printf("Closing path\n");
  444.                 bmp_pline(b,b->sx,b->sy);
  445.         }
  446.         /* printf("pmove %d %d \n",x1,y1); */
  447.         b->sx = x1; b->sy = y1;
  448.         b->x1 = x1; b->y1 = y1;
  449.         b->sddy = -2;
  450.         b->lddy = -2;
  451. }
  452. bmp_pline(Bitmap *b,int x2,int y2)
  453. {
  454.         int dx, dy, dxabs, dyabs, i, j, px, py, sdx, sdy;
  455.         int endy,xwid;
  456.         register int x,y;
  457.         int x1=b->x1, y1=b->y1; /* start of line */
  458.         int lddy=b->lddy;
  459.         int ddy,horizx;
  460.  
  461.         if (x1==x2 && y1==y2) return;   /* not going anywhere */
  462.  
  463.  
  464.  
  465.         if (bmp_clipline(b,&x1,&y1,&x2,&y2)) return;    /* clip to bitmap */
  466. /*  fprintf(fgle,"aline %d %d \n",x2,y2);
  467.         printf("CVector %d,%d  --- %d,%d \n",x1,y1,x2,y2);
  468. */
  469.         b->x1 = x2; b->y1 = y2;     /* remember end of line */
  470.         bmp_minmax(b,y1);
  471.         bmp_minmax(b,y2);   /* remember range of y paint values */
  472.  
  473.         dx = x2 - x1;
  474.         dy = y2 - y1;
  475.         xwid = dx/2;
  476.         sdx = sign(dx);
  477.         sdy = sign(dy);
  478.         dxabs = abs(dx);
  479.         dyabs = abs(dy);
  480.         x = 0;
  481.         y = 0;
  482.         px = x1;
  483.         py = y1;
  484.         endy = y2;
  485.  
  486.         ddy = sdy;
  487.         if (dy==0) ddy = 0; /* ddy = -1, 0, 1 */
  488.         if (ddy==0) {   /* this is a horizontal line */
  489.                 bmp_painth(b,x1,x2,y1);     /* paint the whole line */
  490.                 goto endpline;
  491.         }
  492.         if (lddy == -ddy)  bmp_paintx(b,x1,y1); /* put in last endxy */
  493.         if (dxabs >= dyabs) {
  494.            horizx = px+sdx; /* start of first row */
  495.            for (i=0; i<dxabs; i++) {
  496.                   y += dyabs;
  497.                   if (y>=dxabs) {
  498.                  y -= dxabs;
  499.                  bmp_painth(b,horizx,px,py);    /* end of that row */
  500.                  py += sdy;
  501.                  horizx = px+sdx;   /* start of next row */
  502.                  /* if (py==endy) break; */
  503.                  bmp_paintx(b,px+sdx,py);
  504.                   }
  505.                   px += sdx;
  506.            }
  507.         } else {
  508.            for (i=0; i<dyabs; i++) {
  509.                   x += dxabs;
  510.                   if (x>=dyabs) {
  511.                  x -= dyabs;
  512.                  px += sdx;
  513.                   }
  514.                   py += sdy;
  515.                   bmp_paintx(b,px,py);
  516.            }
  517.         }
  518.  
  519. endpline:
  520.         if (ddy!=0) {   /* remember last line if not horiz */
  521.                 b->lddy = ddy;
  522.                 if (lddy== -2) { /* first line */
  523.                         b->sddy = ddy;
  524.                         b->ssx = x1;
  525.                         b->ssy = y1;
  526.                         return;
  527.                 }
  528.         }
  529.  
  530.         if (x2==b->sx && y2==b->sy) { /* path is closed */
  531.                 if (b->sddy == -b->lddy) { /* direction changed */
  532.                         bmp_paintx(b,b->ssx,b->ssy);
  533.                 }
  534.         }
  535. }
  536.  
  537. bmp_minmax(Bitmap *b,int y)     /* remember range of y paint values */
  538. {
  539.         if (y<b->painty1) b->painty1 = y;
  540.         if (y>b->painty2) b->painty2 = y;
  541. }
  542.  
  543. /*
  544.         Adds x value onto paint[] range table
  545. */
  546. bmpcheck(Bitmap *b)
  547. {
  548.         int i,*p;
  549.  
  550.         for (i=0;i<16;i++) {
  551. /*      p = &(*b->paint)[i][0];
  552.                 printf("P[%d] = %d %d %d %d \n",i,*p,*(p+1),*(p+2),*(p+3));
  553. */
  554.         }
  555. }
  556. bmp_paintx(Bitmap *b, int x, int y)
  557. {
  558.         int *c,nc,i,nrow;
  559.  
  560.  
  561.         i = 0;
  562.         row_grow(&b->paint,y,1);
  563.         c = row_data(b->paint,y);
  564.         c += row_used(b->paint,y) - 1;
  565.         *c = x;
  566.  
  567.         c = row_data(b->paint,y);
  568.         nc = row_used(b->paint,y);
  569. /*
  570.         printf("Paint [%d] x=%d , ",y,x);
  571.         for (i=0;i<nc;i++,c++) {
  572.                 printf("%d ",*c);
  573.         }
  574.         printf("\n");
  575. */
  576. }
  577. row_show(char *s,Run *r,int y)
  578. {
  579.         int i,*c,nc;
  580.  
  581.         c = (*r->row)[y];
  582.         nc = r->used[y];
  583.         printf("show {%s} [%d] ",s,y);
  584.         for (i=0;i<nc;i++,c++) {
  585.                 printf("%d ",*c);
  586.         }
  587.         printf("\n");
  588. }
  589. /*
  590.         This routine remembers the horizontal lines that
  591.         need to be drawn.
  592.  
  593.         They don't need sorting, and they can be amalgamated e.g.
  594.         They do need putting into ascending order when used.
  595.  
  596.                 1 7, 5 9,  can become 1 9
  597. */
  598. showhy(Bitmap *b, int y)
  599. {
  600.         int *c,i;
  601.  
  602.         i = 0;
  603. /*  c = &(*b->horiz)[y][0];
  604.         c = (*b->horiz.row)[y];
  605.         printf("showy ");
  606.         for (;i < (*b->horiz.used)[y];c+=2 ,i+=2) {
  607.                 printf("%d %d ",*c,*(c+1));
  608.         }
  609.         printf("\n");
  610. */
  611. }
  612. bmp_painth(Bitmap *b, int x1,int x2, int y)
  613. {
  614.         int *c,i,nc;
  615.  
  616.         /* printf("Addh, (%d) %d %d \n",y,x1,x2); */
  617.  
  618.         if (x1>x2) {i=x2; x2=x1; x1=i;}
  619.         i = 0;
  620.         c = row_data(b->horiz,y);
  621.         nc = row_used(b->horiz,y);
  622.         for (;i < nc-1 ;c+=2 ,i+=2) {
  623.                 if (*c<=x1 && *(c+1)>=x1) {
  624.                         c++;
  625.                         if (*c < x2) *c = x2;
  626.                         return;
  627.                 }
  628.                 if (*c<=x2 && *(c+1)>=x2) {
  629.                         if (*c > x1) *c = x1;
  630.                         return;
  631.                 }
  632.                 if (*c-1 == x2) { *c = x1; return;}
  633.                 if (*(c+1)+1 == x1) { *(c+1) = x2; return;}
  634.         }
  635.         /* found an empty slot */
  636.  
  637.         row_grow(&b->horiz,y,2); /* make it two bigger */
  638.         c = row_data(b->horiz,y);
  639.         nc = row_used(b->horiz,y);
  640.         c += nc - 2;
  641.         *c = x1;
  642.         *(c+1) = x2;
  643. }
  644.  
  645. /* Clear the current path. */
  646. bmp_newpath(Bitmap *b)
  647. {
  648.         int i,j;
  649.         int *c;
  650.  
  651.         for (i=b->painty1; i<=b->painty2; i++) {
  652.                 row_setused(b->paint,i,0);
  653.                 row_setused(b->horiz,i,0);
  654.         }
  655.         b->painty1 = b->ny+2;
  656.         b->painty2 = 0;
  657.  
  658.         if (farcoreleft()<50000L) row_shrink(b);
  659. }
  660.  
  661. /*
  662.   from painty1 to painty2
  663.         sort x's and call bmp_paint(b,y,x1,x2);
  664. */
  665. bmp_paintsort(int *p, int np)
  666. {
  667.         int *pp = p;
  668.         int a,b,fixed,i;
  669.  
  670.         fixed = true;
  671.         for (;fixed;) {
  672.            fixed = false;
  673.            for (p = pp, i = 0; i<(np-1); i++, p++) {
  674.                   if (*p > *(p+1)) {
  675.                 a = *p;
  676.                 *p = *(p+1);
  677.                 *(p+1) = a;
  678.                 fixed=true;
  679.                   }
  680.            }
  681.         }
  682.         p = pp;
  683. /*
  684.         printf("(sort) ");
  685.         for (;*p!=-2;p++) printf("%d ",*p);
  686.         printf("\n");
  687. */}
  688.  
  689.  
  690. bmp_fill(Bitmap *b)
  691. {
  692.         int i,k,nrow,ncrow,j,x1,x2;
  693.         int *c,*p,np,nc;
  694.  
  695.         /* printf ("Fill, color is %d \n",b->ink[0][0]); */
  696.         if (b->sx != b->x1 || b->sy != b->y1) {
  697.                 printf("Closing path\n");
  698.                 bmp_pline(b,b->sx,b->sy);
  699.         }
  700.         for (i=b->painty1; i<=b->painty2; i++) {
  701.            p = row_data(b->paint,i);
  702.            np = row_used(b->paint,i);
  703.            bmp_paintsort(p,np);
  704.            for (j=0;j<np-1; j+=2, p+=2) {
  705.                   c = row_data(b->clip,i);
  706.                   nc = row_used(b->clip,i);
  707.                   if (!b->clipping) bmp_paintrange(b,i,*p,*(p+1)); /* no clipping */
  708.                   else {
  709.                  for (k=0;k<nc-1; k+=2, c+=2) {
  710.                    x1 = *p; x2 = *(p+1);
  711.                    if (x1< *c) x1 = *c;
  712.                    if (x2> *(c+1)) x2 = *(c+1);
  713.                    if (x1<=x2) bmp_paintrange(b,i,x1,x2); /* clipped range */
  714.                  }
  715.                   }
  716.            }
  717.  
  718.            /* now paint the thin horizontal bits */
  719.            p = row_data(b->horiz,i);
  720.            np = row_used(b->horiz,i);
  721.            for (j=0;j<np-1; j+=2, p+=2) {
  722.                   if (!b->clipping) bmp_paintrange(b,i,*p,*(p+1)); /* no clipping */
  723.                   else {
  724.                          c = row_data(b->clip,i);
  725.                          nc = row_used(b->clip,i);
  726.                          for (k=0;k<nc-1; k+=2, c+=2) {
  727.                    x1 = *p; x2 = *(p+1);
  728.                    if (x1< *c) x1 = *c;
  729.                    if (x2> *(c+1)) x2 = *(c+1);
  730.                    if (x1<=x2) bmp_paintrange(b,i,x1,x2); /* clipped range */
  731.                  }
  732.                   }
  733.            }
  734.            /* end horizontal bits */
  735.         }
  736. }
  737.  
  738.  
  739.  
  740. /* Coppies bitmap on while applying clip (not using ink[])
  741. */
  742. /*
  743. bmp_copy(Bitmap *b,char *bitmap,int nx,int ny)
  744. {
  745. }
  746. */
  747. /* Move paint array onto clip array.  */
  748. bmp_clip(Bitmap *b)
  749. {
  750.         int i;
  751.         int *c,*p,nc;
  752.  
  753.         if (dev_noclip) return;
  754.  
  755.         /* Sort the paint array before copying it */
  756.         for (i=0;i<b->ny; i++) {
  757.                 c = row_data(b->paint,i);
  758.                 bmp_paintsort(c,row_used(b->paint,i));
  759.         }
  760.  
  761.         /* Now simply copy it over */
  762.         for (i=0;i<b->ny; i++) {
  763.                 p = row_data(b->paint,i);
  764.                 nc = row_used(b->paint,i);
  765.  
  766.                 if (nc>0) {
  767.                         row_grow(&b->clip,i,nc);
  768.                         c = row_data(b->clip,i);
  769.                         memcpy(c,p,nc*sizeof(int));
  770.                 }
  771.  
  772.         }
  773.  
  774.         b->clipping = true; /* remeber that clipping is on now */
  775. }
  776.  
  777. /* Clears the clipping array    */
  778. bmp_newclip(Bitmap *b)
  779. {
  780.         int i,j;
  781.         int *c;
  782.  
  783.         if (dev_noclip) return;
  784.         b->clipping = false;
  785.         for (i=0; i<=b->ny+1; i++) {
  786.                 row_setused(b->clip,i,0);
  787.         }
  788. }
  789.  
  790. /*
  791.         Coppies clipping array and lastclip pointer into malloced area
  792.         and sets lastclip to point to this new malloced area.
  793. */
  794. bmp_saveclip(Bitmap *b)
  795. {
  796.         int *c;
  797.  
  798.         if (dev_noclip) return;
  799.         /* should save clipping region */
  800. }
  801.  
  802. bmp_restoreclip(Bitmap *b)
  803. {
  804.         int *c;
  805.         if (dev_noclip) return;
  806.         /* should restore from saved memory but I'm in a hurry */
  807.         b->clipping = false;
  808.  
  809. #ifdef __TURBOC__
  810.         row_shrinkx(&b->clip,b->ny);
  811. #endif
  812. }
  813.  
  814. /*  Sets ink based on a lookup table
  815.         255 = white, 0 = black
  816. */
  817. bmp_color(Bitmap *b,int colindex)
  818. {
  819.         int i,j;
  820.         for (i=0;i<16;i++)
  821.                 for (j=0;j<16;j++)
  822.                 b->ink[i][j] = colindex;
  823. }
  824.  
  825.  
  826. unsigned int grey_bits[] = {0x0000, 0x0200, 0x0802, 0x0a02,
  827.                 0x5050, 0x5250, 0x5852, 0x5a52,
  828.                 0xa5a5, 0xa7a5, 0xada7, 0xafa7,
  829.                 0xf5f5, 0xf7f5, 0xfdf7, 0xfff7, 0xffff};
  830.  
  831.  
  832. static unsigned int pat_shade1[] = {
  833.         0xc000, 0x6000, 0x3000, 0x1800, 0xc00, 0x600, 0x300,
  834.         0x180, 0xc0, 0x60, 0x30, 0x18, 0xc, 0x6, 0x3, 0x8001 };
  835. static unsigned int pat_shade2[] = {
  836.         0xc018, 0x600c, 0x3006, 0x1803, 0x8c01, 0xc600, 0x6300, 0x3180,
  837.         0x18c0, 0xc60, 0x630, 0x318, 0x18c, 0xc6, 0x63, 0x8031 };
  838. static unsigned int pat_shade3[] = {
  839.         0xf078, 0x783c, 0x3c1e, 0x1e0f, 0x8f07, 0xc783, 0xe3c1, 0xf1e0,
  840.         0x78f0, 0x3c78, 0x1e3c, 0xf1e, 0x78f, 0x83c7, 0xc1e3, 0xe0f1 };
  841. static unsigned int pat_shade4[] = {
  842.         0x7e00, 0x3f00, 0x1f80, 0xfc0, 0x7e0, 0x3f0, 0x1f8, 0xfc,
  843.         0x7e, 0x3f, 0x801f, 0xc00f, 0xe007, 0xf003, 0xf801, 0xfc00 };
  844. static unsigned int pat_shade5[] = {
  845.         0x6006,   0x7ffe,0x6006,0x300c,0x1818,0xc30, 0x660, 0x3c0,
  846.         0x660, 0xc30, 0x1998,0x33cc,0x67e6,0x7ffe,0x6006,   0x6006   };
  847. static unsigned int pat_grid1[] = {
  848.         0xc003, 0x6006, 0x300c, 0x1818, 0xc30, 0x660, 0x3c0, 0x180,
  849.         0x3c0, 0x660, 0xc30, 0x1818, 0x300c, 0x6006, 0xc003, 0x8001 };
  850. static unsigned int pat_grid2[] = {
  851.         0xf00f, 0x781e, 0x3c3c, 0x1e78, 0xff0, 0xfe0, 0xfc0, 0xf80,
  852.         0xfc0, 0xfe0, 0xff0, 0x1e78, 0x3c3c, 0x781e, 0xf00f, 0xf00f };
  853. static unsigned int pat_grid3[] = {
  854.         0xffff, 0xffff, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0xffff,
  855.         0xffff, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0xffff, 0xffff};
  856. static unsigned int pat_grid4[] = {
  857.         0x303, 0x303, 0xcfc0, 0xcfc0, 0x3ff0, 0x3ff0, 0xfcc, 0xfcc,
  858.         0x303, 0x303, 0xcc0f, 0xcc0f, 0xf03f, 0xf03f, 0xc0cf, 0xc0cf };
  859. static unsigned int pat_grid5[] = {
  860.         0x300, 0x300, 0x300, 0x300, 0xcc0, 0xcc0, 0xf03f, 0xf03f,
  861.         0x3, 0x3, 0x3, 0x3, 0xc00c, 0xc00c, 0x3ff0, 0x3ff0 };
  862.  
  863.  
  864. #define NGREY 17
  865. bmp_setcolor(Bitmap *bb,int r, int g, int b, int ftyp)
  866. {
  867.         /* values between 0-255 */
  868.         unsigned int i,j,m,nib,k,n,xx,savenib,ix,iy,savem;
  869.         unsigned int *patt;
  870.         int cindex;
  871.         float f;
  872.  
  873.         f = (r*3+g*2+b)/(255*6.0);
  874.  
  875.         i = (1-f)*(NGREY-.8);
  876.         if (f<1 && i==0) i = 1;
  877.  
  878.         savem = grey_bits[i];
  879.  
  880.         /* Fill types,
  881.                 2=pat_black, 3=pat_red, 4=pat_green,
  882.                 5=pat_blue, 6=pat_yellow
  883.         */
  884.  
  885.         if (ftyp>1 && ftyp<7) {
  886.                 cindex = 0;
  887.                 if (ftyp==3) cindex = 1;
  888.                 if (ftyp==4) cindex = 2;
  889.                 if (ftyp==5) cindex = 4;
  890.                 if (ftyp==6) cindex = 3;
  891.                 if (!iscolor) cindex = 0;
  892.                 if (g==0x0 && b==0x20) patt = pat_shade1;
  893.                 if (g==0x0 && b==0x0c) patt = pat_shade1;
  894.                 if (g==0x0 && b==0x10) patt = pat_shade2;
  895.                 if (r==0x5 && b==0x20) patt = pat_shade3;
  896.                 if (g==0x0 && b==0x40) patt = pat_shade4;
  897.                 if (g==0x0 && b==0x60) patt = pat_shade5;
  898.                 if (g==0x20 && b==0x20) patt = pat_grid1;
  899.                 if (g==0xf && b==0xf)   patt = pat_grid1;
  900.                 if (g==0x10 && b==0x10) patt = pat_grid2;
  901.                 if (g==0x20 && b==0x20) patt = pat_grid3;
  902.                 if (g==0x40 && b==0x40) patt = pat_grid4;
  903.                 if (g==0x60 && b==0x60) patt = pat_grid5;
  904.                 bmp_ink16(bb,patt,cindex);
  905.                 return;
  906.         }
  907.         /* 0 = black, 1=red, green, blue, yellow, magenta, brown, ... white */
  908.  
  909.         if (r==g && g==b) {
  910.                 bmp_ink4(bb,savem,0);
  911.                 return;
  912.         }
  913.         if (iscolor) {
  914.                 cindex = -1;
  915.                 if (r>20 && g==0 && b==0) {cindex = 1; f=r;}
  916.                 if (g>20 && r==0 && b==0) {cindex = 2; f=g;}
  917.                 if (b>20 && g==0 && r==0) {cindex = 4; f=b;}
  918.                 if (r>20 && g>20 && b==0) {cindex = 3; f=r;}
  919.                 if (cindex>=0) {
  920.                         f = f/255.0;
  921.                         i = (f)*(NGREY-.8);
  922.                         if (f<1 && i==(NGREY-1)) i = NGREY-2;
  923.                         bmp_ink4(bb,grey_bits[i],cindex);
  924.                         return;
  925.                 }
  926.                 if (r>150 && g<50 && b<50)  cindex = 1;
  927.                 if (r<50 && g>150 && b<50)  cindex = 2;
  928.                 if (r<50 && g<50 && b>150)  cindex = 4;
  929.                 if (r>150 && g>150 && b<50)  cindex = 3;
  930.                 if (b>50 && g>50 && r<18)    cindex = 6; /* CYAN */
  931.                 if (r>50 && b>50 && g<20)  cindex = 5; /* Magenta */
  932.                 if (cindex >= 0) {
  933.                         bmp_color(bb,cindex);
  934.                         return;
  935.                 }
  936.         }
  937.         bmp_ink4(bb,savem,0);
  938. }
  939. bmp_ink4(Bitmap *bb,unsigned int savem,int cindex)
  940. {
  941.         /* values between 0-255 */
  942.         unsigned int i,j,m,nib,k,n,xx,savenib,ix,iy;
  943.         unsigned int *patt;
  944.         float f;
  945.  
  946.         for (ix=0; ix<16; ix+=4) {
  947.           for (iy=0; iy<16; iy+=4) {
  948.                 m = savem;
  949.                 for (j=0; j<4; j++) {
  950.                   nib = m & 0xf;
  951.                   for (k=0; k<4; k++) {
  952.                         if (nib&1) bb->ink[ix+j][iy+k] = cindex;
  953.                         else bb->ink[ix+j][iy+k]  = 15;
  954.                         nib = nib >> 1;
  955.                   }
  956.                   m = m >> 4;
  957.                 }
  958.           }
  959.         }
  960.  
  961. }
  962. bmp_ink16(Bitmap *bb,unsigned int newink[],int cindex)
  963. {
  964.         unsigned int m;
  965.         int i,ix,iy;
  966.  
  967.         for (iy=0; iy<16; iy++) {
  968.                 m = newink[iy];
  969.                 for (ix=15; ix>=0; ix--) {
  970.                         if (m&1 == 1)  bb->ink[iy][ix] = cindex;
  971.                         else bb->ink[iy][ix]  = 15;
  972. /*          printf("ix iy %d %d  %d\n",ix,iy,bb->ink[ix][iy]);
  973. */          m = m >> 1;
  974.                 }
  975.         }
  976. }
  977. bmp_lwidth(Bitmap *b,int x)
  978. {
  979.         b->lwidth = x;
  980. }
  981.  
  982. bmp_lstyle(Bitmap *b,int32 n,int l)
  983.    /* n is a pattern, 01110001110;  l is len of one pattern dot in pixels */
  984. {
  985.         b->lstyle = n;
  986.         b->lstyle_mask = 0x80000000;
  987.         b->lstyle_dotlen = l;
  988.         b->lstyle_dotpix = 0;
  989. }
  990.  
  991. /* (depth must be 1, expands this into the pat[][] array,
  992.         each 1 becomes a 255)
  993. */
  994. /*
  995. bmp_pattern(Bitmap *b,char *pat,int nxbytes,int nybytes,int depth)
  996. {
  997. }
  998. */
  999. /* Returns pointer to a row of the bitmap */
  1000.  
  1001. unsigned char *bmp_expanded(Bitmap *b,int y);
  1002. char *bmp_row(Bitmap *b,int y)
  1003. {
  1004.         pr_ly = -1;
  1005.         if (b->compress) {
  1006.                 return (char *) bmp_expanded(b,y);
  1007.         } else {
  1008.                 return (*b->data)[y];
  1009.         }
  1010. }
  1011. /* this compression routine won't work with more than one 'Bitmap' as
  1012. it doesn't store it's data in Bitmap *b, like it should. */
  1013.  
  1014. unsigned char *bmp_expanded(Bitmap *b,int y)
  1015. {
  1016.         static unsigned char *bitrow,*bitc;
  1017.         static unsigned char *o,*bc,c,*lastv;
  1018.         static int lasty = -2;
  1019.         char *v;
  1020.         int nc,x,i,j,nxbyte;
  1021.         int totwid = 0;
  1022.  
  1023.  
  1024.         if (lasty==y) return bitrow;
  1025.         if (y>b->ny+1) goto return_null;
  1026.         nxbyte = b->nx/8+1;
  1027.         if (iscolor) nxbyte = b->nx/2+2;
  1028.         if (bitrow==NULL) bitrow = (ucharp) calloc(1,nxbyte+3);
  1029.         if (bitc == NULL) bitc = (ucharp) calloc(1,nxbyte*2+3);
  1030.         if (bitrow==NULL || bitc==NULL) bmp_die("bitc allocation error\n");
  1031.         v = (*b->data)[y];
  1032.  
  1033.         if (lasty != -2) {
  1034.           o = bitc;
  1035. /*    if (lasty==296) {
  1036.                  printf("Store [%d]",lasty);
  1037.                   for (i=0;i<nxbyte;i++) printf("%x ",bitrow[i]);
  1038.                   printf("\n");
  1039.           }
  1040. */
  1041.           for (x=0; x<nxbyte ; x++) {
  1042.                 c = bitrow[x];
  1043.                 nc = 1;
  1044.                 for (;x<(nxbyte-1) && bitrow[x+1]==c && nc<250; x++) nc++;
  1045.                 *o++ = nc;
  1046.                 *o++ = c;
  1047.                 totwid = totwid + 2;
  1048.           }
  1049.           if (totwid>nxbyte*2) printf("Total width %d nx=%d\n",totwid,nxbyte);
  1050.          *o++ = 0;
  1051.          *o++ = 0; /* nulls at end */
  1052.          nc = o-bitc+1;
  1053.  
  1054.  
  1055.          if (lastv!=NULL) lastv = (unsigned char *) realloc(lastv,nc);
  1056.           else lastv = (ucharp) malloc(nc);
  1057.           if (lastv==NULL) {
  1058.                 printf("Failed to allocate enough memory for bitmap \n");
  1059.                 abort();
  1060.           }
  1061.           memcpy(lastv,bitc,nc);
  1062.           (*b->data)[lasty] = (char *) lastv;
  1063.         }
  1064.         lasty = y;
  1065.         lastv = (ucharp) v;
  1066.  
  1067.         nc = 0;
  1068.         if (v==NULL) {
  1069. return_null:    memset(bitrow,255,nxbyte);
  1070.                 return bitrow;
  1071.         }
  1072.  
  1073.         nc = 0;
  1074.         bc = (ucharp) v;
  1075.  
  1076.         for (i=0, o = bitrow; bc[i]!=0 ; i+=2) {
  1077.                 for (j=0; j<bc[i]; j++) {
  1078.                         *o++ = bc[i+1]; nc++;
  1079.                         if (nc>nxbyte) {
  1080.  
  1081.                         printf("ERR[%d] ",y);
  1082.                         for (i=0;bc[i]!=0;i+=2) printf("%d,%x ",bc[i],bc[i+1]);
  1083.                         printf("\n");
  1084.  
  1085.  
  1086.                                 printf("gone past end [%d] %d %d \n",y,nxbyte,nc);
  1087.                                 return bitrow;
  1088.                         }
  1089.                 }
  1090.         }
  1091. /*
  1092.         if (y==296) {
  1093.                 printf("EXP[%d] ",y);   for (i=0;i<10;i++) printf("%d ",bitrow[i]);
  1094.                 printf("\n");
  1095.         }
  1096. */
  1097.         return bitrow;
  1098. }
  1099. bmp_die(char *s)
  1100. {
  1101.         printf("%s",s);
  1102.         exit(EXIT_FAILURE);
  1103. }
  1104.  
  1105. bmp_pbezier(Bitmap *bb,int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3)
  1106. {
  1107.         float ax,bx,cx,ay,by,cy,xxx,yyy,t,nstep;
  1108.         int dist,i;
  1109.  
  1110.  
  1111.  
  1112.         dbg printf("pbezier, %d %d   %d %d   %d %d   %d %d \n",x0,y0,x1,y1,x2,y2,x3,y3);
  1113.         dist = abs(x3-x0) + abs(y3-y0);
  1114.         nstep = 20;
  1115.         if (dist<30) nstep = 10;
  1116.         if (dist<10) nstep = 5;
  1117.         if (dist<5) nstep = 3;
  1118.         if (dist<=2) {
  1119.                 bmp_pline(bb,x3,y3);
  1120.                 return;
  1121.         }
  1122.         cx = (x1-x0)*3;
  1123.         bx = (x2-x1)*3-cx;
  1124.         ax = x3-x0-cx-bx;
  1125.         cy = (y1-y0)*3;
  1126.         by = (y2-y1)*3-cy;
  1127.         ay = y3-y0-cy-by;
  1128.         for (i=0;i<=nstep;i++) {
  1129.                 t = (float) i/nstep;
  1130.                 xxx = ax*pow(t,3.0) + bx*t*t + cx*t + x0;
  1131.                 yyy = ay*pow(t,3.0) + by*t*t + cy*t + y0;
  1132.                 bmp_pline(bb,(int) xxx,(int) yyy);
  1133.         }
  1134. }
  1135. bmp_bezier(Bitmap *bb,int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3)
  1136. {
  1137.         float ax,bx,cx,ay,by,cy,xxx,yyy,t,nstep,xx,yy;
  1138.         int dist,i;
  1139.  
  1140.         dist = abs(x3-x0) + abs(y3-y0);
  1141.         nstep = 20;
  1142.         if (dist<30) nstep = 10;
  1143.         if (dist<10) nstep = 5;
  1144.         if (dist<5) nstep = 3;
  1145.         if (dist<=2) {
  1146.                 bmp_line(bb,x0,y0,x3,y3);
  1147.                 return;
  1148.         }
  1149.         cx = (x1-x0)*3;
  1150.         bx = (x2-x1)*3-cx;
  1151.         ax = x3-x0-cx-bx;
  1152.         cy = (y1-y0)*3;
  1153.         by = (y2-y1)*3-cy;
  1154.         ay = y3-y0-cy-by;
  1155.         xx = x0; yy = y0;
  1156.         for (i=0;i<=nstep;i++) {
  1157.                 t = (float) i/nstep;
  1158.                 xxx = ax*pow(t,3.0) + bx*t*t + cx*t + x0;
  1159.                 yyy = ay*pow(t,3.0) + by*t*t + cy*t + y0;
  1160.                 bmp_line(bb,(int) xx,(int) yy, (int) xxx, (int) yyy);
  1161.                 xx = xxx; yy = yyy;
  1162.         }
  1163. }
  1164.  
  1165. #define OUTCODES_CSD( X, Y, OUTCODE )           \
  1166.         ( OUTCODE ) = 0;                            \
  1167.         if ((Y) >= b->ny )          OUTCODE |= 1; \
  1168.         else  if ((Y) < 0 )    OUTCODE |= 2; \
  1169.         if ((X) >= b->nx  )          OUTCODE |= 4; \
  1170.         else  if ((X) < 0 )    OUTCODE |= 8;
  1171.  
  1172. int bmp_clipline(Bitmap *b,int *x1, int *y1, int *x2, int *y2)
  1173. {
  1174.         int outcode1,outcode2;
  1175.  
  1176.         OUTCODES_CSD( *x2, *y2, outcode2 );
  1177.         OUTCODES_CSD( *x1, *y1, outcode1 );
  1178.  
  1179.                 if (outcode1 & outcode2)         /* trivial reject */
  1180.                 return true; /* throw line away */
  1181.         if (!(outcode2 | outcode1))    /* trivial accept */
  1182.                 return false;
  1183.  
  1184.         doclip(0,b->nx-1,x1);
  1185.         doclip(0,b->nx-1,x2);
  1186.         doclip(0,b->ny-1,y1);
  1187.         doclip(0,b->ny-1,y2);
  1188.         return false;
  1189. }
  1190. doclip(int min, int max, int *v)
  1191. {
  1192.         if (*v < min) *v = min;
  1193.         if (*v > max) *v = max;
  1194. }
  1195.  
  1196. showfree()
  1197. {
  1198. #ifdef __TURBOC__
  1199.    struct farheapinfo hi;
  1200.    int32 total=0;
  1201.  
  1202.    hi.ptr = NULL;
  1203.    while( farheapwalk( &hi ) == _HEAPOK ) {
  1204.         if (!hi.in_use) total += hi.size;
  1205.    }
  1206.    printf("Total mem free %ld \n",total);
  1207. #endif
  1208. }
  1209.  
  1210.  
  1211.